package com.dasberg.gwt.server;

import com.dasberg.gwt.client.AuthenticationException;
import com.dasberg.gwt.client.AuthenticationToken;
import com.dasberg.gwt.domain.IRole;
import com.dasberg.gwt.domain.IToken;
import com.dasberg.gwt.domain.hibernate.Token;
import com.dasberg.gwt.domain.hibernate.User;
import com.google.inject.Inject;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import java.util.Date;

/** @author mischa */
public class DbAuthenticationProvider implements AuthenticationProvider {
    @Inject
    private Session session;

    /** Constructor. */
    public DbAuthenticationProvider() {
    }

    /** {@inheritDoc}. */
    public boolean isTokenValid(AuthenticationToken authenticationToken) {
        Token token = (Token) session.createCriteria(Token.class).add(Restrictions.eq("uuid", authenticationToken.getId())).uniqueResult();
        boolean valid = (token != null && token.getExpirationDate().after(new Date()) && token.getUser().getUsername().equals(authenticationToken.getUsername()));
        // If the authentication token is still valid update the expiration date.
        if (valid) {
            token.updateExpirationDate();
            session.update(token);
        }
        return valid;
    }

    /** {@inheritDoc}. */
    public IToken authenticate(String username, String password) throws AuthenticationException {
        User user = (User) session.createCriteria(User.class).
                add(Restrictions.eq("username", username)).
                add(Restrictions.eq("password", password)).
                add(Restrictions.eq("enabled", true)).
                add(Restrictions.eq("accountExpired", false)).
                add(Restrictions.eq("accountLocked", false)).
                uniqueResult();
        if (user != null) {
            Token token = new Token();
            token.setUser(user);
            session.save(token);
            return token;
        } else {
            throw new AuthenticationException("Username or password are invalid.");
        }
    }

    /** {@inheritDoc}. */
    public void deauthenticate(AuthenticationToken authenticationToken) {
        Token token = (Token) session.createCriteria(Token.class).add(Restrictions.eq("uuid", authenticationToken.getId())).uniqueResult();
        if (token != null) {
            session.delete(token);
        }
    }

    /** {@inheritDoc}. */
    public boolean isUserInRole(AuthenticationToken token, String role) {
        User user = (User) session.createCriteria(User.class).add(Restrictions.eq("username", token.getUsername())).uniqueResult();
        if(user!= null) {
            for(IRole r : user.getRoles()) {
                if(r.getName().equals(role)) {
                    return true;
                }
            }
        }
        return false;
    }
}
